package org.six11.ss.server;

import java.io.IOException;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.hibernate.Query;
import org.six11.ss.server.bean.*;
import org.six11.util.Debug;
import org.six11.util.adt.MultiState;

/**
 * 
 * 
 * @author Gabe Johnson <johnsogg@cmu.edu>
 */
public class BrowseWebActionHandler extends WebActionHandler {

  public static Comparator<Sketch> sketchComparator = new Comparator<Sketch>() {
    public int compare(Sketch o1, Sketch o2) {
      return ((Integer) o1.getId()).compareTo(o2.getId());
    }
  };

  /**
   * @param actionName
   * @param jsp
   * @param ms
   */
  public BrowseWebActionHandler(String actionName, String jsp, MultiState ms) {
    super(actionName, jsp, ms);
  }

  @SuppressWarnings("unchecked")
  public Set<Sketch> getRecentSketches() {
    Set<Sketch> sketches = new TreeSet<Sketch>(sketchComparator);
    List<Sketch> recent = getHibernate().createQuery(
        "from Sketch as s where s.data is not null order by id desc").setMaxResults(5).list();
    sketches.addAll(recent);
    return sketches;
  }

  /**
   * 
   */
  @SuppressWarnings("unchecked")
  @Override
  public void handle(HttpServletRequest req, HttpServletResponse resp, ServletContext context)
      throws ServletException, IOException {
    Set<Sketch> sketches = new TreeSet<Sketch>(sketchComparator);

    String pSketchID = req.getParameter("sketchID");
    String pClueID = req.getParameter("clueID");
    String pPersonID = req.getParameter("personID");
    String pGameID = req.getParameter("gameID");
    String pThemeID = req.getParameter("themeID");
    String pKeyword = req.getParameter("keyword");
    String pPageNum = req.getParameter("pageNum");
    String pPageSize = req.getParameter("pageSize");
    
    String reason = null;

    if (ok(pSketchID)) {
      sketches.add(loadSketch(pSketchID));
      reason = "Showing a sketch.";
    }
    if (ok(pClueID)) {
      Clue clue = loadClue(pClueID);
      List<Sketch> res = (List<Sketch>) getHibernate().createQuery(
          "select sketch from Round as r where r.clue = ?")
          .setInteger(0, Integer.parseInt(pClueID)).list();
      sketches.addAll(res);
      bug("browse by clue. the set is now: " + Debug.num(sketches, " "));
      reason = "Showing sketches based on the clue '" + clue.getName() + "'.";
    }

    if (ok(pPersonID)) {
      Person person = loadPerson(pPersonID);
      List<Sketch> res = (List<Sketch>) getHibernate().createQuery(
          "select sketch from Round as r where r.sketcher = ?").setInteger(0,
          Integer.parseInt(pPersonID)).list();
      sketches.addAll(res);
      bug("browse by person. the set is now: " + Debug.num(sketches, " "));
      reason = "Showing sketches made by " + person.getNick();
    }

    if (ok(pGameID)) {
      Game game = loadGame(pGameID);
      List<Sketch> res = (List<Sketch>) getHibernate().createQuery(
          "select sketch from Round as r where r.game = ?").setInteger(0, game.getId()).list();
      sketches.addAll(res);
      bug("browse by game. the set is now: " + Debug.num(sketches, " "));
      reason = "Showing sketches made during game " + game.getId() + ".";
    }
    if (ok(pThemeID)) {
      // a bit trickier... get the games associated with this theme, then get all the sketches
      // associated with all of those games.
      Theme theme = loadTheme(pThemeID);
      List<Game> games = (List<Game>) getHibernate().createQuery(
          "from Game as game where game.theme = ?").setInteger(0, theme.getId()).list();
      for (Game g : games) {
        List<Sketch> res = (List<Sketch>) getHibernate().createQuery(
            "select sketch from Round as r where r.game = ?").setInteger(0, g.getId()).list();
        sketches.addAll(res);
      }
      bug("browse by theme. the set is now: " + Debug.num(sketches, " "));
      reason = "Showing sketches based on the theme '" + theme.getName() + "'";
      req.setAttribute("link", "./?a=themes&themeID=" + theme.getId());
      req.setAttribute("linkText", "You can add clues to this theme!");
    }
    if (ok(pKeyword)) {
      // TODO: implement me
      reason = "Showing sketches with label " + pKeyword;
    }

    if (reason == null) {
      // user did not request anything. Show everything!
      bug("Showing everything!");
      try {
        Query q = getHibernate().createQuery(
            "from Sketch as s where s.data is not null order by s.id desc");
        int pageSize = pPageSize == null ? 20 : Integer.parseInt(pPageSize);
        int pageNum = pPageNum == null ? 0 : Integer.parseInt(pPageNum);
        bug("Browsing from entire database. Page: " + pageNum + ", # each page: " + pageSize);
        q.setMaxResults(pageSize);
        q.setFirstResult(pageNum * pageSize);
        if (pageNum > 0) {
          req.setAttribute("pagePrev", pageNum - 1);
        }
        req.setAttribute("pageNext", pageNum + 1);
        req.setAttribute("pageSize", pageSize);
        List<Sketch> res = q.list();
        sketches.addAll(res);
      } catch (Throwable t) {
        bug("Got throwable...");
        t.printStackTrace();
      }
    }

    req.setAttribute("reason", reason);

    if (sketches.size() == 1) {
      req.setAttribute("sketch", sketches.toArray(new Sketch[1])[0]);
    } else if (sketches.size() > 0) {
      req.setAttribute("sketches", sketches);
    }
    forwardTo(jsp, req, resp, context);
  }

}
